关键词:GNU/Linux;串口通讯;并口I/O操作;usb存储设备 中图分类号:Tll 文献标识码:A The Applications of the General I/O in the GNU/Linux LIU Yang,ZHOU Chun-jie (Department of Control Science and Engineering, HuaZhong University of Science & Technology, WuHan 430074, China) Abstract: This paper introduced the detailed operations of three kinds of the general I/O in the GNU/ Linux on the x86 platform, which are the serial communication, the standard parallel ports and the usb mass- storage devices. Key words: GNLT/Linux; serial communication; parallel ports; usb mass - storage 1 引言 GNU/Linux是一个开放源代码,通用的,符合 POSIX(IEEE Standard Portable Operating System Interface for Computer Environment)标准的操作系统。其健壮、稳定、功能强大的特点,在服务器领域与嵌入式设备上极为流行。在通常的PCx86体系下,常用的标准I/O操作有三种:串口,并口、USB口与网口。GNU/Linux作为一种类UNIX系统继承了UNIX的传统,将所有I/0操作都作为一种特殊的文件操作,程序员只需用通常的open()、 read()、write()、ioctl()、close()等函数就可以完成大部分的操作,大大减轻了软件开发的难度,提高了开发的效率与可靠性,而这些I/O、的组合使用又基本可以满足大部分系统的应用。本文以一个实际系统为例,说明了基于PCx86体系下的串口、并口与USB口操作,网口由于其本身的特殊性,在本文就不作为一般的I/O介绍了。系统硬件示意图如下,主控板为一块586级的嵌入式主板PCM一5820,主频为300Mhz、外扩128Mb内存、16M电子盘,主控板自带两个串口,一个标准25针并口,两个USB口等接口;需要完成的功能有:与下层的一块51为核心的按键显示板通讯,读入键值与刷新显示;同时还需每10ms采集8路开关量输入,通过一定的程序处理后输出1路开关量;并不定期对采集的数据记录做备份。实际系统正常工作时,实现长时间无人值守与可靠运行,本身要求有较高的稳定性。本文将从串口、并口、USB口三个方面介绍。
2 串口通讯实现 根据按键显示板本身对通讯要求,具有一定的偶发性和要求有交互性,我们利用主控板上的串口选用RS232的通讯方式。由于在Linux下,串口一般作为一个终端接口,即tty接口,POSIX.1定义了一个查询和操作终端的标准接口,该接口被称作 termios,在系统的头文件
中定义。 termios是一个数据结构和一系列操作这些数据结构的函数。 #include struct termios{ tcflag-t c-iflag;/*指明输入方式的标志位*/ tcflag-t c-oflag;/*指明输出方式的标志位*/ tcflag-t c-cflag;/*指明控制方式的标志位*/ tcflag-t c-lflag;/*指明局部方式的标志位*/ cc-t c-line;/*指明分行定义*/ cc-t C-CC[NCCS];/*指明用于控制的特殊字符*/ speed-t c-ispeed;/*指明输入传输速度*/ speed-t c-ospeed;/*指明输出传输速度*/ } 对终端访问的控制函数如下: 这些函数一起共构成了通用的终端界面,提供对终端的有效控制操作,使得系统具有复杂的异步串口设备处理能力[4]。 RS232C只是一个物理层接口,为了保障数据传输的准确性与可靠性,须用户自己保证数据传输正确,根据本系统通讯的特点:如果发生通讯,每次主机只会从按键显示板接收到一帧包含按键信息的数据,而每次按键都是独立事件;主控板向键盘显示板发送一定数据更新显示。按照此需求,定义通讯协议如下:接收时,每帧数据长度为5字节,发送时,每帧数据长度为12字节,波特率为9600B/s,1位停止位,8位数据位,不带奇偶校验。发送与接收的帧格式都是一样的,帧首字节固定为0x55,第二个字节是本帧数据长度,最末两字节为校验和,其余为数据;紧跟着两个相邻数据包之间没有关系,不需要帧序号,同时两板之间距离很近,干扰源较少,因此误码率很低,用和校验就可保证传输的误码率。具体设计实现如下: 具体设计时为了保证一定的系统响应速度,同时尽量减少主控板系统资源的使用,使用Linux下的信号驱动机制,使用SIGIO信号,当有下位机传按键至主控板时,操作系统发出一个信号,用户程序进入信号处理程序。初始化串口时,调用open()函数,打开设备文件ttyS0,发送和接收数据时就可以直接使用read()和write()函数,类似文件一样使用串口。 3 并口操作实现 并口,有时也称打印口,最初设计用于连接计算机和打印机。许多年后,其他很多设备也通过并口与计算机进行连接,例如扫描仪、可移动设备和复制保护设备等。现代PC上,并口有8根双向数据线、四根双向控制线以及5根状态输入线,他们通过一个DB一25凹口连接器供外部进行访问。从并口发明之初到现在,共发展出4种类型,实际系统中,主板的bios可以设置并口类型,本系统将主控板设为标准并口类型(SPP)。 在GNU/Linux下,一般对于PC并口进行数据采集和控制有3种方法。第一种方法使用端口 I/O,简单、操作性强,并且可以清楚说明编写设备驱动程序开发所必需的底层硬件控制过程。第二种方法使用Linux并口设备驱动程序ppdev来控制并口。这种方法与通过使用设备驱动程序及 ioctl系统调用进行串口控制的方法相似。第三种方法创建自己订制的并口驱动程序,这个并口驱动 程序使用/proc目录。本系统要求达到每10ms采集一次开关量的要求,并根据运算结果,输出一个开关量;可以利用并口中的pin2 - pin9数据口,一次将8个开关量全部采集,并通过程序判断,输出结果至pin1口。采用第一种方法就能满足本系统的要求,因此具体实现如下: 在Linux中有一个用于输入的命令inb(ad— dress)和一个用于输出的命令outb(value,address)。 C语言的宏扩展实现了这两个函数,而且不涉及任何函数库,但使用这两个函数需要一些额外的函数,函数ioperm()从内核中申请和释放端口访问权[7]。 向并口写入一个字节代码如下: if(ioperm(0x378,3,1) ) exit (1); outb ( LP-DATA, 0x378); if( ioperm(0X378,3,0 )) exit(1); 从并口读人一个字节代码如下: if(ioperm(Ox378,3,1)) exit(1); putc(inb(Ox378) ); if( ioperm(OX378,3,0)) exit (1); 只要在上述代码增加少量代码就可以作为一个完整的代码。这种方法也有缺点,只有root用户才能调用ioperm函数,这会影响没有root权限的用户使用该程序,而且如果用户想使用除了数据位以外的控制位作为输出或输入信号锁存输出值时,则会带来很大困难,另外,这样的程序实现可重入,将会面临很大难度。但在本系统中,由于正式系统不存在用户登录的问题,同时,并口只会被本进程使用,不存在重入的问题。 为了保证每10ms的读一次并口,利用Linux系统中的信号机制,使用settimer()函数,每10ms产生一次SIGALRM信号,在这个信号的中断函数里,采集一次开关量。保证了系统的实时性T4。 4 USB口用于数据备份具体实现 由于系统是24小时不停机的长时间运行,本身采集的数据量是比较大的,可是主控板本身的存储空间很小,而现场不具备安装网线的条件,所以需要考虑一种尽可能不增加硬件投资,又可以获得高可靠性,同时考虑到数据量比较大,对传输速率要求比较高,一般的串口已经无法满足要求,因此,采用USB的传输方案,利用u盘将现场的数据暂存,回到控制中心,再将数据倒入数据库。另外,为了减少工作人员的工作量,利用Linux本身特有的 RAMDISK功能,将内存中分出70Mb作为暂存区,并将这部分作为系统的另一个分区,在系统启动的时候,直接挂载到系统中。 对于2.4.x的内核来说,USB存储设备驱动已经集成在内核里,但驱动程序只与Linux SCSI层交互。这意味着,在配置内核时,除了配置USB选项之外,还需要配置某些SCSI选项,选择支持合适的文件系统。在内核已支持USB存储设备的情况下,当USB设备接人系统的USB口后,直接使用外部命令mount和umount的命令就可以将 USB存储设备挂载到系统和解除挂载了。用cp等外部命令就可以将需要备份的数据从暂存区移动至USB存储设备中。在程序中,使用system函数可以完成对外部命令程序的调用。具体实现过程如下: 1、检测外部USB设备是否挂载到系统上,检查/proc/bus/usb/deviees文件,是否已经正确挂载上去,其次,根据/proc/scsi/目录中设备文件的内容,生成mount命令的第一个参数;2、用system函数调用mount命令,将USB存储设备挂载至文件系统节点/mnt下; 3、用system函数调用cp命令,将ramdisk中的内容拷贝到该目录下; 4、用system函数调用umount命令,将移动介质卸载调。 5 总结 系统已经在现场运行了半年,从运行的效果来看,串口通讯采用IO信号驱动的方式完全可以适应其偶发性与一定的实时性,并口经常作为IO数据的采集与输出,采用定时扫描,而linux2.4.26操作系统的最小时间间隙100Hz,保证了每10ms采集一次的要求;USB口由于其传输数据量大、可靠,作为大数据量与交换,在Linux下,所有u盘和活动硬盘必须遵循USB mass—storage协议才能稳定可靠运行。另外,针对不同的硬件应该制作不同的Linux内核,充分利用内核的模块化,使用最少模块的内核,完成尽可能多的任务。现在系统已经开始实际运行,从运行的效果来开,所有的指标都可以满足当初的设计要求,本身Linux系统的稳定性,完全可以实现无人值守。 参考文献 [1] (美)Kurt Wall等.张辉译.GNU/Linx编程指南(第二版)[M].北京:清华